home *** CD-ROM | disk | FTP | other *** search
/ Network PC / Network PC.iso / amiga utilities / communication / bbs / termv4.6 / extras / source / term-source.lha / Console.c < prev    next >
Encoding:
C/C++ Source or Header  |  1996-03-18  |  52.4 KB  |  3,214 lines

  1. /*
  2. **    Console.c
  3. **
  4. **    High-level terminal console routines
  5. **
  6. **    Copyright © 1990-1996 by Olaf `Olsen' Barthel
  7. **        All Rights Reserved
  8. */
  9.  
  10. #ifndef _GLOBAL_H
  11. #include "Global.h"
  12. #endif
  13.  
  14.     /* Character set modes. */
  15.  
  16. enum    {    MODE_STANDARD,MODE_GFX };
  17.  
  18.     /* Hints for the data flow scanner. */
  19.  
  20. STATIC WORD    ScanStart,
  21.         ScanEnd;
  22.  
  23. STATIC WORD    AttentionCount[SCAN_COUNT],
  24.         AttentionLength[SCAN_COUNT],
  25.         FlowCount;
  26.  
  27.     /* Temporary console working buffer. */
  28.  
  29. STATIC UBYTE    ConTempBuffer[512];
  30.  
  31.     /* ConTranslateSetup():
  32.      *
  33.      *    Set up for buffer translation.
  34.      */
  35.  
  36. STATIC VOID
  37. ConTranslateSetup(struct TranslationHandle *Handle,STRPTR SourceBuffer,LONG SourceLen,STRPTR DestinationBuffer,LONG DestinationLen,struct TranslationEntry **Table)
  38. {
  39.     Handle -> LocalBuffer        = NULL;
  40.     Handle -> LocalLen        = 0;
  41.  
  42.     Handle -> SourceBuffer        = SourceBuffer;
  43.     Handle -> SourceLen        = SourceLen;
  44.  
  45.     Handle -> DestinationBuffer    = DestinationBuffer;
  46.     Handle -> DestinationLen    = DestinationLen;
  47.  
  48.     Handle -> Table            = Table;
  49. }
  50.  
  51.     /* ConTranslateBuffer(struct TranslationHandle *Handle):
  52.      *
  53.      *    Translate buffer contents according to
  54.      *    translation table contents.
  55.      */
  56.  
  57. STATIC LONG
  58. ConTranslateBuffer(struct TranslationHandle *Handle)
  59. {
  60.     register STRPTR                 Data        = Handle -> DestinationBuffer;
  61.     register LONG                 BytesWritten    = 0;
  62.     register struct TranslationEntry    *Entry;
  63.  
  64.         /* Are we to return any translated data? */
  65.  
  66.     while(Handle -> LocalLen && BytesWritten < Handle -> DestinationLen)
  67.     {
  68.             /* Decrement number of bytes in buffer. */
  69.  
  70.         Handle -> LocalLen--;
  71.  
  72.             /* Return next character. */
  73.  
  74.         *Data++ = *Handle -> LocalBuffer++;
  75.  
  76.             /* Add another byte. */
  77.  
  78.         BytesWritten++;
  79.     }
  80.  
  81.         /* Loop until done. */
  82.  
  83.     while(Handle -> SourceLen && BytesWritten < Handle -> DestinationLen)
  84.     {
  85.             /* Another byte eaten. */
  86.  
  87.         Handle -> SourceLen--;
  88.  
  89.             /* Get table entry. */
  90.  
  91.         if(Entry = Handle -> Table[*Handle -> SourceBuffer++])
  92.         {
  93.                 /* Copy to local data area. */
  94.  
  95.             Handle -> LocalBuffer    = Entry -> String;
  96.             Handle -> LocalLen    = Entry -> Len;
  97.  
  98.                 /* Translate the data. */
  99.  
  100.             while(Handle -> LocalLen && BytesWritten < Handle -> DestinationLen)
  101.             {
  102.                     /* Decrement number of bytes in buffer. */
  103.  
  104.                 Handle -> LocalLen--;
  105.  
  106.                     /* Return next character. */
  107.  
  108.                 *Data++ = *Handle -> LocalBuffer++;
  109.  
  110.                     /* Add another byte. */
  111.  
  112.                 BytesWritten++;
  113.             }
  114.         }
  115.     }
  116.  
  117.     return(BytesWritten);
  118. }
  119.  
  120.     /* TrapFilter(register STRPTR Data,register LONG Size):
  121.      *
  122.      *    Handle the trap list, similar to FlowFilter().
  123.      */
  124.  
  125. STATIC VOID
  126. TrapFilter(register STRPTR Data,register LONG Size)
  127. {
  128.     if(Size)
  129.     {
  130.         STATIC LONG WaitCount = 0;
  131.  
  132.         struct List    *List = (struct List *)&GenericListTable[GLIST_TRAP] -> ListHeader;
  133.         struct TrapNode    *Node;
  134.  
  135.         register LONG c,Mask;
  136.  
  137.         ObtainSemaphore(&GenericListTable[GLIST_TRAP] -> ListSemaphore);
  138.  
  139.         if(Config -> SerialConfig -> StripBit8)
  140.             Mask = 0x7F;
  141.         else
  142.             Mask = 0xFF;
  143.  
  144.         do
  145.         {
  146.             register BOOL MatchMade;
  147.  
  148.             c = (*Data++) & Mask;
  149.  
  150.             do
  151.             {
  152.                 MatchMade = FALSE;
  153.  
  154.                 for(Node = (struct TrapNode *)List -> lh_Head ; Node -> Node . ln_Succ ; Node = (struct TrapNode *)Node -> Node . ln_Succ)
  155.                 {
  156.                     if(Node -> Count == WaitCount)
  157.                     {
  158.                         if(c == (Node -> Sequence[WaitCount] & Mask))
  159.                         {
  160.                             MatchMade = TRUE;
  161.  
  162.                             if(++Node -> Count == Node -> SequenceLen)
  163.                             {
  164.                                 struct DataMsg *Msg;
  165.  
  166.                                 Node -> Count = 0;
  167.  
  168.                                 if(Msg = (struct DataMsg *)CreateMsgItem(sizeof(struct DataMsg) + strlen(Node -> Command) + 1))
  169.                                 {
  170.                                     Msg -> Type = DATAMSGTYPE_SERIALCOMMAND;
  171.                                     Msg -> Data = (STRPTR)(Msg + 1);
  172.  
  173.                                     strcpy(Msg -> Data,Node -> Command);
  174.  
  175.                                     PutMsgItem(SpecialQueue,(struct MsgItem *)Msg);
  176.                                 }
  177.                             }
  178.                         }
  179.                     }
  180.                 }
  181.  
  182.                 if(MatchMade)
  183.                     WaitCount++;
  184.                 else
  185.                 {
  186.                     if(WaitCount)
  187.                     {
  188.                         WaitCount = 0;
  189.  
  190.                         for(Node = (struct TrapNode *)List -> lh_Head ; Node -> Node . ln_Succ ; Node = (struct TrapNode *)Node -> Node . ln_Succ)
  191.                             Node -> Count = 0;
  192.                     }
  193.                     else
  194.                         break;
  195.                 }
  196.             }
  197.             while(!WaitCount);
  198.         }
  199.         while(--Size);
  200.  
  201.         ReleaseSemaphore(&GenericListTable[GLIST_TRAP] -> ListSemaphore);
  202.     }
  203. }
  204.  
  205.     /* FlowFilter(register STRPTR Data,register LONG Size,UBYTE Mask):
  206.      *
  207.      *    Data flow filter.
  208.      */
  209.  
  210. STATIC VOID
  211. FlowFilter(register STRPTR Data,register LONG Size,register UBYTE Mask)
  212. {
  213.     register LONG c;
  214.  
  215.         /* Run until done. */
  216.  
  217.     do
  218.     {
  219.         if(c = (*Data++ & Mask))
  220.         {
  221.  
  222.                 /* We already got a `CONNECT',
  223.                  * Continue scanning the serial output
  224.                  * data for the actual baud rate.
  225.                  */
  226.  
  227.             if(BaudPending)
  228.             {
  229.                 if(c < ' ')
  230.                 {
  231.                     while(BaudCount > 0 && BaudBuffer[BaudCount - 1] == ' ')
  232.                         BaudCount--;
  233.  
  234.                     BaudBuffer[BaudCount] = 0;
  235.  
  236.                     FlowInfo . Connect = TRUE;
  237.                     FlowInfo . Changed = TRUE;
  238.  
  239.                     BaudPending = FALSE;
  240.  
  241.                     DTERate = GetBaudRate(BaudBuffer);
  242.  
  243.                     if(Quiet && Size > 1)
  244.                     {
  245.                         DataHold = Data;
  246.                         DataSize = Size - 1;
  247.                     }
  248.                 }
  249.                 else
  250.                 {
  251.                     if(BaudCount || c != ' ')
  252.                     {
  253.                         BaudBuffer[BaudCount++] = c;
  254.  
  255.                         if(BaudCount == 79)
  256.                         {
  257.                             while(BaudCount > 0 && BaudBuffer[BaudCount - 1] == ' ')
  258.                                 BaudCount--;
  259.  
  260.                             BaudBuffer[BaudCount] = 0;
  261.  
  262.                             FlowInfo . Connect = TRUE;
  263.                             FlowInfo . Changed = TRUE;
  264.  
  265.                             BaudPending = FALSE;
  266.  
  267.                             DTERate = GetBaudRate(BaudBuffer);
  268.  
  269.                             if(Quiet && Size > 1)
  270.                             {
  271.                                 DataHold = Data;
  272.                                 DataSize = Size - 1;
  273.                             }
  274.                         }
  275.                     }
  276.                 }
  277.             }
  278.             else
  279.             {
  280.                 register BOOL MatchMade;
  281.                 register LONG i;
  282.  
  283.                 do
  284.                 {
  285.                     MatchMade = FALSE;
  286.  
  287.                         /* Scan all ID strings for matches. */
  288.  
  289.                     for(i = ScanStart ; i <= ScanEnd ; i++)
  290.                     {
  291.                             /* This sequence is a likely
  292.                              * match.
  293.                              */
  294.  
  295.                         if(AttentionCount[i] == FlowCount)
  296.                         {
  297.                                 /* Does the character
  298.                                  * fit into the sequence?
  299.                                  */
  300.  
  301.                             if(c == AttentionBuffers[i][FlowCount] & Mask)
  302.                             {
  303.                                 MatchMade = TRUE;
  304.  
  305.                                     /* Did we hit the
  306.                                      * last character
  307.                                      * in the sequence?
  308.                                      */
  309.  
  310.                                 if(++AttentionCount[i] == AttentionLength[i])
  311.                                 {
  312.                                         /* We've got a valid
  313.                                          * sequence, now look
  314.                                          * which flags to change.
  315.                                          */
  316.  
  317.                                     switch(i)
  318.                                     {
  319.                                             /* We got a `no carrier' message. */
  320.  
  321.                                         case SCAN_NOCARRIER:
  322.  
  323.                                             if(!FlowInfo . NoCarrier)
  324.                                             {
  325.                                                 FlowInfo . NoCarrier    = TRUE;
  326.                                                 FlowInfo . Changed    = TRUE;
  327.                                             }
  328.  
  329.                                             break;
  330.  
  331.                                             /* Got another call. */
  332.  
  333.                                         case SCAN_RING:
  334.  
  335.                                             if(!FlowInfo . Ring)
  336.                                             {
  337.                                                 FlowInfo . Ring        = TRUE;
  338.                                                 FlowInfo . Changed    = TRUE;
  339.                                             }
  340.  
  341.                                             break;
  342.  
  343.                                             /* Got a voice call. */
  344.  
  345.                                         case SCAN_VOICE:
  346.  
  347.                                             if(!FlowInfo . Voice)
  348.                                             {
  349.                                                 FlowInfo . Voice    = TRUE;
  350.                                                 FlowInfo . Changed    = TRUE;
  351.                                             }
  352.  
  353.                                             break;
  354.  
  355.                                             /* Modem reported an error. */
  356.  
  357.                                         case SCAN_ERROR:
  358.  
  359.                                             if(!FlowInfo . Error)
  360.                                             {
  361.                                                 FlowInfo . Error    = TRUE;
  362.                                                 FlowInfo . Changed    = TRUE;
  363.                                             }
  364.  
  365.                                             break;
  366.  
  367.                                             /* Got a connect message. */
  368.  
  369.                                         case SCAN_CONNECT:
  370.  
  371.                                             if(!Online)
  372.                                             {
  373.                                                 BaudBuffer[0]    = 0;
  374.  
  375.                                                 BaudPending    = TRUE;
  376.                                                 BaudCount    = 0;
  377.                                             }
  378.  
  379.                                             break;
  380.  
  381.                                             /* Line is busy. */
  382.  
  383.                                         case SCAN_BUSY:
  384.  
  385.                                             if(!FlowInfo . Busy)
  386.                                             {
  387.                                                 FlowInfo . Busy        = TRUE;
  388.                                                 FlowInfo . Changed    = TRUE;
  389.                                             }
  390.  
  391.                                             break;
  392.  
  393.                                         case SCAN_NODIALTONE:
  394.  
  395.                                             if(!FlowInfo . NoDialTone)
  396.                                             {
  397.                                                 FlowInfo . NoDialTone    = TRUE;
  398.                                                 FlowInfo . Changed    = TRUE;
  399.                                             }
  400.  
  401.                                             break;
  402.  
  403.                                             /* Modem accepted a command. */
  404.  
  405.                                         case SCAN_OK:
  406.  
  407.                                             if(!FlowInfo . Ok)
  408.                                             {
  409.                                                 FlowInfo . Ok        = TRUE;
  410.                                                 FlowInfo . Changed    = TRUE;
  411.                                             }
  412.  
  413.                                             break;
  414.  
  415.                                         default:
  416.  
  417.                                             if(!FlowInfo . Signature)
  418.                                             {
  419.                                                 FlowInfo . Signature    = i;
  420.                                                 FlowInfo . Changed    = TRUE;
  421.                                             }
  422.  
  423.                                             break;
  424.                                     }
  425.                                 }
  426.                             }
  427.                         }
  428.                     }
  429.  
  430.                     if(MatchMade)
  431.                         FlowCount++;
  432.                     else
  433.                     {
  434.                         if(FlowCount)
  435.                         {
  436.                             FlowCount = 0;
  437.  
  438.                             memset(AttentionCount,0,sizeof(AttentionCount));
  439.                         }
  440.                         else
  441.                             break;
  442.                     }
  443.                 }
  444.                 while(!FlowCount);
  445.             }
  446.         }
  447.     }
  448.     while(--Size);
  449. }
  450.  
  451.     /* ConOutputPrinter(STRPTR Buffer,LONG Size):
  452.      *
  453.      *    Raw text output routine, printer capture flavour.
  454.      */
  455.  
  456. STATIC VOID
  457. ConOutputPrinter(STRPTR Buffer,LONG Size)
  458. {
  459.     if(Write(PrinterCapture,Buffer,Size) != Size)
  460.     {
  461.         BlockWindows();
  462.  
  463.         if(!ShowRequest(NULL,LocaleString(MSG_CONSOLE_ERROR_WRITING_TO_PRINTER_TXT),LocaleString(MSG_CONSOLE_IGNORE_CLOSE_PRINTER_TXT)))
  464.             ClosePrinterCapture(TRUE);
  465.  
  466.         ReleaseWindows();
  467.     }
  468. }
  469.  
  470.     /* ConOutputGFX(STRPTR Buffer,LONG Size):
  471.      *
  472.      *    Raw text output routine, GFX text flavour.
  473.      */
  474.  
  475. STATIC VOID
  476. ConOutputGFX(STRPTR Buffer,LONG Size)
  477. {
  478.     register LONG Offset;
  479.  
  480.         /* Do we still have a character in the
  481.          * magnificient buffer?
  482.          */
  483.  
  484.     while(Size)
  485.     {
  486.             /* Cursor is positioned at
  487.              * the right hand side of the
  488.              * display. If auto-wrap is
  489.              * enabled, perform some
  490.              * kind of CR/LF, else leave
  491.              * the cursor where it is and
  492.              * quit the show.
  493.              */
  494.  
  495.         if(CursorX > LastPrintableColumn)
  496.         {
  497.                 /* Wrap cursor. */
  498.  
  499.             if(Config -> EmulationConfig -> LineWrap)
  500.             {
  501.                     /* Move to beginning of next line. */
  502.  
  503.                 CursorX = 0;
  504.  
  505.                 DownLine();
  506.  
  507.                     /* Reposition cursor, don't redraw it. */
  508.  
  509.                 RepositionCursor();
  510.             }
  511.             else
  512.             {
  513.                     /* Stop the cursor. */
  514.  
  515.                 CursorX = LastPrintableColumn;
  516.  
  517.                     /* Make it reappear. */
  518.  
  519.                 RepositionCursor();
  520.  
  521.                 return;
  522.             }
  523.         }
  524.  
  525.         if((Offset = LastPrintableColumn + 1 - CursorX) > Size)
  526.             Offset = Size;
  527.  
  528.         if(Config -> EmulationConfig -> InsertMode)
  529.         {
  530.             RasterShiftChar(Offset);
  531.  
  532.             ScrollLineShiftChar(Offset);
  533.  
  534.             ShiftChar(Offset);
  535.         }
  536.  
  537.         RasterPutString(Buffer,Offset);
  538.  
  539.         ScrollLinePutString(Offset);
  540.  
  541.         if(FontScalingRequired)
  542.             PrintScaled(Buffer,Offset,CurrentFontScale);
  543.         else
  544.             GfxText(RPort,Buffer,Offset);
  545.  
  546.         Buffer    += Offset;
  547.  
  548.         Size    -= Offset;
  549.  
  550.         CursorX    += Offset;
  551.     }
  552.  
  553.     RepositionCursor();
  554. }
  555.  
  556.     /* ConOutputNormal(STRPTR Buffer,LONG Size):
  557.      *
  558.      *    Raw text output routine, normal text flavour.
  559.      */
  560.  
  561. STATIC VOID
  562. ConOutputNormal(STRPTR Buffer,LONG Size)
  563. {
  564.     register LONG Offset;
  565.  
  566.     while(Size)
  567.     {
  568.         if(CursorX > LastPrintableColumn)
  569.         {
  570.             if(Config -> EmulationConfig -> LineWrap)
  571.             {
  572.                 CursorX = 0;
  573.  
  574.                 DownLine();
  575.  
  576.                 RepositionCursor();
  577.             }
  578.             else
  579.             {
  580.                 CursorX = LastPrintableColumn;
  581.  
  582.                 RepositionCursor();
  583.  
  584.                 return;
  585.             }
  586.         }
  587.  
  588.         if((Offset = LastPrintableColumn + 1 - CursorX) > Size)
  589.             Offset = Size;
  590.  
  591.         if(Config -> EmulationConfig -> InsertMode)
  592.         {
  593.             RasterShiftChar(Offset);
  594.  
  595.             ScrollLineShiftChar(Offset);
  596.  
  597.             ShiftChar(Offset);
  598.         }
  599.  
  600.         RasterPutString(Buffer,Offset);
  601.  
  602.         ScrollLinePutString(Offset);
  603.  
  604.         if(FontScalingRequired)
  605.             PrintScaled(Buffer,Offset,CurrentFontScale);
  606.         else
  607.             Text(RPort,Buffer,Offset);
  608.  
  609.         Buffer    += Offset;
  610.  
  611.         Size    -= Offset;
  612.  
  613.         CursorX    += Offset;
  614.     }
  615.  
  616.     RepositionCursor();
  617. }
  618.  
  619.     /* ConProcessUpdate():
  620.      *
  621.      *    Choose the right console data processing routine.
  622.      */
  623.  
  624. VOID
  625. ConProcessUpdate()
  626. {
  627.     Forbid();
  628.  
  629.     if(XEmulatorBase && Config -> TerminalConfig -> EmulationMode == EMULATION_EXTERNAL)
  630.     {
  631.         if(ReceiveTable)
  632.             ConProcessData = ConProcessDataTransExternal;
  633.         else
  634.             ConProcessData = ConProcessDataExternal;
  635.     }
  636.     else
  637.     {
  638.         if(Config -> SerialConfig -> StripBit8)
  639.         {
  640.             if(Config -> TerminalConfig -> EmulationMode == EMULATION_HEX)
  641.                 ConProcessData = ConProcessDataHex7;
  642.             else
  643.                 ConProcessData = ConProcessData7;
  644.         }
  645.         else
  646.         {
  647.             if(Config -> TerminalConfig -> EmulationMode == EMULATION_HEX)
  648.                 ConProcessData = ConProcessDataHex8;
  649.             else
  650.                 ConProcessData = ConProcessData8;
  651.         }
  652.     }
  653.  
  654.     Permit();
  655. }
  656.  
  657.     /* ConOutputUpdate():
  658.      *
  659.      *    Choose the right raw text output routine for the job.
  660.      */
  661.  
  662. VOID
  663. ConOutputUpdate()
  664. {
  665.     Forbid();
  666.  
  667.     if(Config -> CaptureConfig -> BufferMode == BUFFERMODE_FLOW)
  668.         SaveRaster = SaveRasterDummy;
  669.     else
  670.         SaveRaster = SaveRasterReal;
  671.  
  672.     if(BufferFrozen || Config -> CaptureConfig -> BufferMode != BUFFERMODE_FLOW)
  673.     {
  674.         if(FileCapture)
  675.         {
  676.             if(PrinterCapture)
  677.             {
  678.                 if(Config -> CaptureConfig -> CaptureFilterMode && !RawCapture)
  679.                     CaptureData = CaptureFilteredTo_File_Printer;
  680.                 else
  681.                     CaptureData = CaptureRawTo_File_Printer;
  682.             }
  683.             else
  684.             {
  685.                 if(Config -> CaptureConfig -> CaptureFilterMode && !RawCapture)
  686.                     CaptureData = CaptureFilteredTo_File;
  687.                 else
  688.                     CaptureData = CaptureRawTo_File;
  689.             }
  690.         }
  691.         else
  692.         {
  693.             if(PrinterCapture)
  694.             {
  695.                 if(Config -> CaptureConfig -> CaptureFilterMode && !RawCapture)
  696.                     CaptureData = CaptureFilteredTo_Printer;
  697.                 else
  698.                     CaptureData = CaptureRawTo_Printer;
  699.             }
  700.             else
  701.                 CaptureData = NULL;
  702.         }
  703.     }
  704.     else
  705.     {
  706.         if(FileCapture)
  707.         {
  708.             if(PrinterCapture)
  709.             {
  710.                 if(Config -> CaptureConfig -> CaptureFilterMode && !RawCapture)
  711.                     CaptureData = CaptureFilteredTo_Buffer_File_Printer;
  712.                 else
  713.                     CaptureData = CaptureRawTo_Buffer_File_Printer;
  714.             }
  715.             else
  716.             {
  717.                 if(Config -> CaptureConfig -> CaptureFilterMode && !RawCapture)
  718.                     CaptureData = CaptureFilteredTo_Buffer_File;
  719.                 else
  720.                     CaptureData = CaptureRawTo_Buffer_File;
  721.             }
  722.         }
  723.         else
  724.         {
  725.             if(PrinterCapture)
  726.             {
  727.                 if(Config -> CaptureConfig -> CaptureFilterMode && !RawCapture)
  728.                     CaptureData = CaptureFilteredTo_Buffer_Printer;
  729.                 else
  730.                     CaptureData = CaptureRawTo_Buffer_Printer;
  731.             }
  732.             else
  733.             {
  734.                 if(Config -> CaptureConfig -> CaptureFilterMode && !RawCapture)
  735.                     CaptureData = CaptureFilteredTo_Buffer;
  736.                 else
  737.                     CaptureData = CaptureRawTo_Buffer;
  738.             }
  739.         }
  740.     }
  741.  
  742.     if(ControllerActive)
  743.         ConOutput = ConOutputPrinter;
  744.     else
  745.     {
  746.         if(CurrentFont == GFX)
  747.             ConOutput = ConOutputGFX;
  748.         else
  749.             ConOutput = ConOutputNormal;
  750.     }
  751.  
  752.     if(ReceiveTable)
  753.         ConDump = ConTransWrite;
  754.     else
  755.         ConDump = ConOutput;
  756.  
  757.     Permit();
  758. }
  759.  
  760.     /* ConFontScaleUpdate():
  761.      *
  762.      *    Choose the right font scale for the job.
  763.      */
  764.  
  765. VOID
  766. ConFontScaleUpdate()
  767. {
  768.     CurrentFontScale    = RasterAttr[CursorY];
  769.     FontScalingRequired    = FALSE;
  770.     CharCellNominator    = 1;
  771.  
  772.     if(CurrentCharWidth == SCALE_HALF)
  773.         CharCellDenominator = 2;
  774.     else
  775.         CharCellDenominator = 1;
  776.  
  777.     if(CurrentFontScale == SCALE_ATTR_NORMAL)
  778.     {
  779.         if(CurrentCharWidth == SCALE_HALF)
  780.         {
  781.                 // Half of normal width
  782.  
  783.             LastPrintableColumn    = (LastColumn + 1) * 2 - 1;
  784.             LastPrintablePixel     = (LastPixel + 1) * 2 - 1;
  785.             FontScalingRequired    = TRUE;
  786.         }
  787.         else
  788.         {
  789.                 // Normal width
  790.  
  791.             LastPrintableColumn    = LastColumn;
  792.             LastPrintablePixel    = LastPixel;
  793.         }
  794.     }
  795.     else
  796.     {
  797.         if(CurrentCharWidth == SCALE_HALF)
  798.         {
  799.                 // Half of double width
  800.  
  801.             LastPrintableColumn    = LastColumn;
  802.             LastPrintablePixel    = LastPixel;
  803.         }
  804.         else
  805.         {
  806.                 // Double width
  807.  
  808.             LastPrintableColumn    = ((LastColumn + 1) / 2) - 1;
  809.             LastPrintablePixel    = ((LastPixel + 1) / 2) - 1;
  810.             FontScalingRequired    = TRUE;
  811.         }
  812.     }
  813. }
  814.  
  815.     /* ConTransWrite(STRPTR Buffer,LONG Size):
  816.      *
  817.      *    Frontend for ConWrite(), including character translation.
  818.      */
  819.  
  820. VOID
  821. ConTransWrite(STRPTR Buffer,LONG Size)
  822. {
  823.     struct TranslationHandle    Handle;
  824.     UBYTE                LocalBuffer[256];
  825.  
  826.         /* Set up for translation. */
  827.  
  828.     ConTranslateSetup(&Handle,Buffer,Size,LocalBuffer,256,ReceiveTable);
  829.  
  830.         /* Process and output the data. */
  831.  
  832.     while(Size = ConTranslateBuffer(&Handle))
  833.         (* ConOutput)(LocalBuffer,Size);
  834. }
  835.  
  836.     /* ConProcessDataTransExternal(register STRPTR String,register LONG Size):
  837.      *
  838.      *    Process data, external emulation including translation flavour.
  839.      */
  840.  
  841. VOID
  842. ConProcessDataTransExternal(register STRPTR String,register LONG Size)
  843. {
  844.     struct TranslationHandle Handle;
  845.  
  846.         /* Set up for translation. */
  847.  
  848.     ConTranslateSetup(&Handle,String,Size,ConTempBuffer,256,ReceiveTable);
  849.  
  850.     if(StripBuffer)
  851.     {
  852.         register LONG Len;
  853.  
  854.             /* Process and output the data. */
  855.  
  856.         while(Size = ConTranslateBuffer(&Handle))
  857.         {
  858.             XEmulatorWrite(XEM_IO,ConTempBuffer,Size);
  859.  
  860.             XEM_HostData . Source        = ConTempBuffer;
  861.             XEM_HostData . Destination    = StripBuffer;
  862.  
  863.             if(Len = XEmulatorHostMon(XEM_IO,&XEM_HostData,Size))
  864.             {
  865.                 if(CaptureData)
  866.                     (*CaptureData)(StripBuffer,Len);
  867.             }
  868.         }
  869.     }
  870.     else
  871.     {
  872.             /* Process and output the data. */
  873.  
  874.         while(Size = ConTranslateBuffer(&Handle))
  875.             XEmulatorWrite(XEM_IO,ConTempBuffer,Size);
  876.     }
  877. }
  878.  
  879.     /* ConProcessDataExternal(register STRPTR String,register LONG Size):
  880.      *
  881.      *    Process data, external emulation flavour.
  882.      */
  883.  
  884. VOID
  885. ConProcessDataExternal(register STRPTR String,register LONG Size)
  886. {
  887.     XEmulatorWrite(XEM_IO,String,Size);
  888.  
  889.         /* Build another string to contain
  890.          * the pure ASCII contents, i.e.
  891.          * not including any ESC control
  892.          * sequences.
  893.          */
  894.  
  895.     if(StripBuffer)
  896.     {
  897.         register LONG Len;
  898.  
  899.         XEM_HostData . Source        = String;
  900.         XEM_HostData . Destination    = StripBuffer;
  901.  
  902.         if(Len = XEmulatorHostMon(XEM_IO,&XEM_HostData,Size))
  903.         {
  904.             if(CaptureData)
  905.                 (*CaptureData)(StripBuffer,Len);
  906.         }
  907.     }
  908. }
  909.  
  910.     /* ConProcessData7(register STRPTR String,register LONG Size):
  911.      *
  912.      *    Process data, 7 bit flavour.
  913.      */
  914.  
  915. VOID
  916. ConProcessData7(register STRPTR String,register LONG Size)
  917. {
  918.     register LONG    Len = 0;
  919.     register UBYTE    c;
  920.  
  921.         /* If still parsing a sequence,
  922.          * continue with it.
  923.          */
  924.  
  925.     if(InSequence)
  926.     {
  927.         while(Size--)
  928.         {
  929.             c = *String++ & 0x7F;
  930.  
  931.             if(!(*AbortTable[c])(c))
  932.             {
  933.                 InSequence = FALSE;
  934.  
  935.                 break;
  936.             }
  937.         }
  938.     }
  939.  
  940.         /* Check which font we are in, if other than Topaz
  941.          * the only invalid char is a Null (0) which will
  942.          * display as a space if let to continue.
  943.          */
  944.  
  945.     if(Config -> TerminalConfig -> FontMode == FONT_STANDARD)
  946.     {
  947.         while(Size-- > 0)
  948.         {
  949.             if(IsPrintable[c = *String++ & 0x7F])
  950.             {
  951.                     /* This character is associated with a
  952.                      * special function (bell, xon, xoff, etc.).
  953.                      */
  954.  
  955.                 if(SpecialTable[c])
  956.                 {
  957.                     if(Len)
  958.                     {
  959.                         (*ConDump)(ConTempBuffer,Len);
  960.  
  961.                         Len = 0;
  962.                     }
  963.  
  964.                         /* Does this character start
  965.                          * a control sequence?
  966.                          */
  967.  
  968.                     if(InSequence = (*SpecialTable[c])(c))
  969.                     {
  970.                         while(Size-- > 0)
  971.                         {
  972.                             c = *String++ & 0x7F;
  973.  
  974.                             if(!(*AbortTable[c])(c))
  975.                             {
  976.                                 InSequence = FALSE;
  977.  
  978.                                 break;
  979.                             }
  980.                         }
  981.                     }
  982.                 }
  983.                 else
  984.                 {
  985.                         /* Put the character into the buffer
  986.                          * and flush it if necessary.
  987.                          */
  988.  
  989.                     ConTempBuffer[Len] = c;
  990.  
  991.                     if(Len++ == 512)
  992.                     {
  993.                         (*ConDump)(ConTempBuffer,Len);
  994.  
  995.                         Len = 0;
  996.                     }
  997.                 }
  998.             }
  999.         }
  1000.     }
  1001.     else
  1002.     {
  1003.         while(Size-- > 0)
  1004.         {
  1005.             if(c = (*String++ & 0x7F))
  1006.             {
  1007.                     /* This character is associated with a
  1008.                      * special function (bell, xon, xoff, etc.).
  1009.                      */
  1010.  
  1011.                 if(SpecialTable[c])
  1012.                 {
  1013.                     if(Len)
  1014.                     {
  1015.                         (*ConDump)(ConTempBuffer,Len);
  1016.  
  1017.                         Len = 0;
  1018.                     }
  1019.  
  1020.                     if(InSequence = (*SpecialTable[c])(c))
  1021.                     {
  1022.                         while(Size-- > 0)
  1023.                         {
  1024.                             c = *String++ & 0x7F;
  1025.  
  1026.                             if(!(*AbortTable[c])(c))
  1027.                             {
  1028.                                 InSequence = FALSE;
  1029.  
  1030.                                 break;
  1031.                             }
  1032.                         }
  1033.                     }
  1034.                 }
  1035.                 else
  1036.                 {
  1037.                         /* Put the character into the buffer
  1038.                          * and flush it if necessary.
  1039.                          */
  1040.  
  1041.                     ConTempBuffer[Len] = c;
  1042.  
  1043.                     if(Len++ == 512)
  1044.                     {
  1045.                         (*ConDump)(ConTempBuffer,Len);
  1046.  
  1047.                         Len = 0;
  1048.                     }
  1049.                 }
  1050.             }
  1051.         }
  1052.     }
  1053.  
  1054.     if(Len)
  1055.         (*ConDump)(ConTempBuffer,Len);
  1056. }
  1057.  
  1058.     /* ConProcessData8(register STRPTR String,register LONG Size):
  1059.      *
  1060.      *    Process data, 8 bit flavour.
  1061.      */
  1062.  
  1063. VOID
  1064. ConProcessData8(register STRPTR String,register LONG Size)
  1065. {
  1066.     register LONG    Len = 0;
  1067.     register UBYTE    c;
  1068.  
  1069.     if(InSequence)
  1070.     {
  1071.         while(Size--)
  1072.         {
  1073.             c = *String++;
  1074.  
  1075.             if(!(*AbortTable[c])(c))
  1076.             {
  1077.                 InSequence = FALSE;
  1078.  
  1079.                 break;
  1080.             }
  1081.         }
  1082.     }
  1083.  
  1084.     if(Config -> TerminalConfig -> FontMode == FONT_STANDARD)
  1085.     {
  1086.         while(Size-- > 0)
  1087.         {
  1088.             if(IsPrintable[c = *String++])
  1089.             {
  1090.                 if(SpecialTable[c])
  1091.                 {
  1092.                     if(Len)
  1093.                     {
  1094.                         (*ConDump)(ConTempBuffer,Len);
  1095.  
  1096.                         Len = 0;
  1097.                     }
  1098.  
  1099.                     if(InSequence = (*SpecialTable[c])(c))
  1100.                     {
  1101.                         while(Size-- > 0)
  1102.                         {
  1103.                             c = *String++;
  1104.  
  1105.                             if(!(*AbortTable[c])(c))
  1106.                             {
  1107.                                 InSequence = FALSE;
  1108.  
  1109.                                 break;
  1110.                             }
  1111.                         }
  1112.                     }
  1113.                 }
  1114.                 else
  1115.                 {
  1116.                     ConTempBuffer[Len] = c;
  1117.  
  1118.                     if(Len++ == 512)
  1119.                     {
  1120.                         (*ConDump)(ConTempBuffer,Len);
  1121.  
  1122.                         Len = 0;
  1123.                     }
  1124.                 }
  1125.             }
  1126.         }
  1127.     }
  1128.     else
  1129.     {
  1130.         while(Size-- > 0)
  1131.         {
  1132.             if(c = *String++)
  1133.             {
  1134.                 if(SpecialTable[c])
  1135.                 {
  1136.                     if(Len)
  1137.                     {
  1138.                         (*ConDump)(ConTempBuffer,Len);
  1139.  
  1140.                         Len = 0;
  1141.                     }
  1142.  
  1143.                     if(InSequence = (*SpecialTable[c])(c))
  1144.                     {
  1145.                         while(Size-- > 0)
  1146.                         {
  1147.                             c = *String++;
  1148.  
  1149.                             if(!(*AbortTable[c])(c))
  1150.                             {
  1151.                                 InSequence = FALSE;
  1152.  
  1153.                                 break;
  1154.                             }
  1155.                         }
  1156.                     }
  1157.                 }
  1158.                 else
  1159.                 {
  1160.                     ConTempBuffer[Len] = c;
  1161.  
  1162.                     if(Len++ == 512)
  1163.                     {
  1164.                         (*ConDump)(ConTempBuffer,Len);
  1165.  
  1166.                         Len = 0;
  1167.                     }
  1168.                 }
  1169.             }
  1170.         }
  1171.     }
  1172.  
  1173.     if(Len)
  1174.         (*ConDump)(ConTempBuffer,Len);
  1175. }
  1176.  
  1177.     /* ConProcessDataHex7(register STRPTR String,register LONG Size):
  1178.      *
  1179.      *    Process data, hex mode flavour, seven bits.
  1180.      */
  1181.  
  1182. VOID
  1183. ConProcessDataHex7(register STRPTR String,register LONG Size)
  1184. {
  1185.     UBYTE    DummyBuffer[40],c;
  1186.     LONG    Fit,Spaces,Current;
  1187.  
  1188.         /* How many characters will fit into the line? */
  1189.  
  1190.     Fit    = (LastColumn + 1) / 4;
  1191.  
  1192.         /* Which position are we currently in? */
  1193.  
  1194.     Current    = CursorX / 3;
  1195.  
  1196.         /* Weird cursor position? */
  1197.  
  1198.     if(Current >= Fit || (CursorX % 3))
  1199.     {
  1200.         ConProcessData7("\r\n",2);
  1201.  
  1202.         Current = 0;
  1203.     }
  1204.  
  1205.         /* Check the font type. */
  1206.  
  1207.     if(Config -> TerminalConfig -> FontMode == FONT_STANDARD)
  1208.     {
  1209.         while(Size-- > 0)
  1210.         {
  1211.             c = (*String++) & 0x7F;
  1212.  
  1213.             Spaces = (Fit - Current) * 3 + Current - 3;
  1214.  
  1215.             if(c > ' ' && c < 127)
  1216.                 SPrintf(DummyBuffer,"%02lx \33[%ldC%lc\33[%ldD",c,Spaces,c,Spaces + 1);
  1217.             else
  1218.                 SPrintf(DummyBuffer,"%02lx \33[%ldC.\33[%ldD",c,Spaces,Spaces + 1);
  1219.  
  1220.             ConProcessData7(DummyBuffer,strlen(DummyBuffer));
  1221.  
  1222.             if(Current++ == Fit - 1)
  1223.             {
  1224.                 Current = 0;
  1225.  
  1226.                 ConProcessData7("\r\n",2);
  1227.             }
  1228.         }
  1229.     }
  1230.     else
  1231.     {
  1232.         while(Size-- > 0)
  1233.         {
  1234.             c = (*String++) & 0x7F;
  1235.  
  1236.             Spaces = (Fit - Current) * 3 + Current - 3;
  1237.  
  1238.             if(c && c != ' ')
  1239.                 SPrintf(DummyBuffer,"%02lx \33[%ldC%lc\33[%ldD",c,Spaces,c,Spaces + 1);
  1240.             else
  1241.                 SPrintf(DummyBuffer,"%02lx \33[%ldC.\33[%ldD",c,Spaces,Spaces + 1);
  1242.  
  1243.             ConProcessData7(DummyBuffer,strlen(DummyBuffer));
  1244.  
  1245.             if(Current++ == Fit - 1)
  1246.             {
  1247.                 Current = 0;
  1248.  
  1249.                 ConProcessData7("\r\n",2);
  1250.             }
  1251.         }
  1252.     }
  1253. }
  1254.  
  1255.     /* ConProcessDataHex8(register STRPTR String,register LONG Size):
  1256.      *
  1257.      *    Process data, hex mode flavour, eight bits.
  1258.      */
  1259.  
  1260. VOID
  1261. ConProcessDataHex8(register STRPTR String,register LONG Size)
  1262. {
  1263.     UBYTE    DummyBuffer[40],c;
  1264.     LONG    Fit,Spaces,Current;
  1265.  
  1266.         /* How many characters will fit into the line? */
  1267.  
  1268.     Fit    = (LastColumn + 1) / 4;
  1269.  
  1270.         /* Which position are we currently in? */
  1271.  
  1272.     Current    = CursorX / 3;
  1273.  
  1274.         /* Weird cursor position? */
  1275.  
  1276.     if(Current >= Fit || (CursorX % 3))
  1277.     {
  1278.         ConProcessData8("\r\n",2);
  1279.  
  1280.         Current = 0;
  1281.     }
  1282.  
  1283.         /* Check the font type. */
  1284.  
  1285.     if(Config -> TerminalConfig -> FontMode == FONT_STANDARD)
  1286.     {
  1287.         while(Size-- > 0)
  1288.         {
  1289.             c = *String++;
  1290.  
  1291.             Spaces = (Fit - Current) * 3 + Current - 3;
  1292.  
  1293.             if((c > ' ' && c < 127) || c > 160)
  1294.                 SPrintf(DummyBuffer,"%02lx \33[%ldC%lc\33[%ldD",c,Spaces,c,Spaces + 1);
  1295.             else
  1296.                 SPrintf(DummyBuffer,"%02lx \33[%ldC.\33[%ldD",c,Spaces,Spaces + 1);
  1297.  
  1298.             ConProcessData8(DummyBuffer,strlen(DummyBuffer));
  1299.  
  1300.             if(Current++ == Fit - 1)
  1301.             {
  1302.                 Current = 0;
  1303.  
  1304.                 ConProcessData8("\r\n",2);
  1305.             }
  1306.         }
  1307.     }
  1308.     else
  1309.     {
  1310.         while(Size-- > 0)
  1311.         {
  1312.             c = *String++;
  1313.  
  1314.             Spaces = (Fit - Current) * 3 + Current - 3;
  1315.  
  1316.             if(c && c != ' ')
  1317.                 SPrintf(DummyBuffer,"%02lx \33[%ldC%lc\33[%ldD",c,Spaces,c,Spaces + 1);
  1318.             else
  1319.                 SPrintf(DummyBuffer,"%02lx \33[%ldC.\33[%ldD",c,Spaces,Spaces + 1);
  1320.  
  1321.             ConProcessData8(DummyBuffer,strlen(DummyBuffer));
  1322.  
  1323.             if(Current++ == Fit - 1)
  1324.             {
  1325.                 Current = 0;
  1326.  
  1327.                 ConProcessData8("\r\n",2);
  1328.             }
  1329.         }
  1330.     }
  1331. }
  1332.  
  1333.     /* ConTransferHost(STRPTR Buffer,LONG Len):
  1334.      *
  1335.      *    Process data read from the serial line,
  1336.      *    special XPR flavour.
  1337.      */
  1338.  
  1339. VOID
  1340. ConTransferHost(STRPTR Buffer,LONG Len)
  1341. {
  1342.     LONG MaxSize;
  1343.  
  1344.     if(Buffer != ReadBuffer)
  1345.         MaxSize = SerialBufferSize - ((LONG)Buffer - (LONG)ReadBuffer);
  1346.     else
  1347.         MaxSize = SerialBufferSize;
  1348.  
  1349.     Len = XProtocolHostMon(XprIO,Buffer,Len,MaxSize);
  1350.  
  1351.     if(TransferWindow)
  1352.         TransferCleanup();
  1353.  
  1354.     if(Len)
  1355.         ConProcess(Buffer,Len);
  1356. }
  1357.  
  1358.     /* ConsoleCommand(STRPTR String):
  1359.      *
  1360.      *    Just like SerialCommand(), but addresses the local
  1361.      *    terminal side.
  1362.      */
  1363.  
  1364. VOID
  1365. ConsoleCommand(STRPTR String)
  1366. {
  1367.     STATIC UBYTE LocalBuffer[256];
  1368.  
  1369.     LONG    Count = 0,i,Len = strlen(String);
  1370.  
  1371.     BOOL    GotControl    = FALSE,
  1372.         GotEscape    = FALSE;
  1373.  
  1374.         /* Scan the string. */
  1375.  
  1376.     for(i = 0 ; i < Len ; i++)
  1377.     {
  1378.             /* We are looking for plain characters
  1379.              * and the control ('\') and escape
  1380.              * ('^') characters.
  1381.              */
  1382.  
  1383.         if(!GotControl && !GotEscape)
  1384.         {
  1385.                 /* Got a control character,
  1386.                  * the next byte will probably be
  1387.                  * a command sequence.
  1388.                  */
  1389.  
  1390.             if(String[i] == '\\')
  1391.             {
  1392.                 GotControl = TRUE;
  1393.  
  1394.                 continue;
  1395.             }
  1396.  
  1397.                 /* Got an escape character,
  1398.                  * the next byte will be some
  1399.                  * kind of control character
  1400.                  * (such as XON, XOF, bell, etc.).
  1401.                  */
  1402.  
  1403.             if(String[i] == '^')
  1404.             {
  1405.                 GotEscape = TRUE;
  1406.  
  1407.                 continue;
  1408.             }
  1409.  
  1410.                 /* This tells us to wait another
  1411.                  * second before continuing with
  1412.                  * the scanning.
  1413.                  */
  1414.  
  1415.             if(String[i] == '~')
  1416.                 continue;
  1417.  
  1418.                 /* Stuff the character into the
  1419.                  * buffer.
  1420.                  */
  1421.  
  1422.             LocalBuffer[Count++] = String[i];
  1423.         }
  1424.         else
  1425.         {
  1426.                 /* Convert the character to a control
  1427.                  * style character (^C, etc.).
  1428.                  */
  1429.  
  1430.             if(GotEscape)
  1431.             {
  1432.                 if(ToUpper(String[i]) >= 'A' && ToUpper(String[i]) <= '_')
  1433.                     LocalBuffer[Count++] = ToUpper(String[i]) - '@';
  1434.                 else
  1435.                     LocalBuffer[Count++] = String[i];
  1436.  
  1437.                 GotEscape = FALSE;
  1438.             }
  1439.  
  1440.                 /* The next character represents a command. */
  1441.  
  1442.             if(GotControl)
  1443.             {
  1444.                 switch(ToUpper(String[i]))
  1445.                 {
  1446.                         /* Translate code. */
  1447.  
  1448.                     case '*':
  1449.  
  1450.                         i++;
  1451.  
  1452.                         while(i < Len && String[i] == ' ')
  1453.                             i++;
  1454.  
  1455.                         if(i < Len)
  1456.                         {
  1457.                             UBYTE DummyBuffer[5],j = 0,Char;
  1458.  
  1459.                             if(String[i] >= '0' && String[i] <= '9')
  1460.                             {
  1461.                                 while(j < 3 && i < Len)
  1462.                                 {
  1463.                                     Char = String[i++];
  1464.  
  1465.                                     if(Char >= '0' && Char <= '9')
  1466.                                         DummyBuffer[j++] = Char;
  1467.                                     else
  1468.                                     {
  1469.                                         i--;
  1470.  
  1471.                                         break;
  1472.                                     }
  1473.                                 }
  1474.                             }
  1475.                             else
  1476.                             {
  1477.                                 while(j < 4 && i < Len)
  1478.                                 {
  1479.                                     Char = ToLower(String[i++]);
  1480.  
  1481.                                     if((Char >= '0' && Char <= '9') || (Char >= 'a' && Char <= 'z'))
  1482.                                         DummyBuffer[j++] = Char;
  1483.                                     else
  1484.                                     {
  1485.                                         i--;
  1486.  
  1487.                                         break;
  1488.                                     }
  1489.                                 }
  1490.                             }
  1491.  
  1492.                             DummyBuffer[j] = 0;
  1493.  
  1494.                             LocalBuffer[Count++] = NameToCode(DummyBuffer);
  1495.                         }
  1496.  
  1497.                         i--;
  1498.  
  1499.                         break;
  1500.  
  1501.                         /* Execute an AmigaDOS command. */
  1502.  
  1503.                     case 'D':
  1504.  
  1505.                         return;
  1506.  
  1507.                         /* Execute an ARexx command. */
  1508.  
  1509.                     case 'A':
  1510.  
  1511.                         return;
  1512.  
  1513.                         /* Add the control character ('\'). */
  1514.  
  1515.                     case '\\':
  1516.  
  1517.                         LocalBuffer[Count++] = '\\';
  1518.                         break;
  1519.  
  1520.                         /* This is a backspace. */
  1521.  
  1522.                     case 'B':
  1523.  
  1524.                         LocalBuffer[Count++] = '\b';
  1525.                         break;
  1526.  
  1527.                         /* This is a form feed. */
  1528.  
  1529.                     case 'F':
  1530.  
  1531.                         LocalBuffer[Count++] = '\f';
  1532.                         break;
  1533.  
  1534.                         /* This is a line feed. */
  1535.  
  1536.                     case 'N':
  1537.  
  1538.                         LocalBuffer[Count++] = '\n';
  1539.                         break;
  1540.  
  1541.                         /* Send the current password. */
  1542.  
  1543.                     case 'P':
  1544.  
  1545.                         break;
  1546.  
  1547.                         /* This is a carriage return. */
  1548.  
  1549.                     case 'R':
  1550.  
  1551.                         LocalBuffer[Count++] = '\r';
  1552.                         break;
  1553.  
  1554.                         /* This is a tab. */
  1555.  
  1556.                     case 'T':
  1557.  
  1558.                         LocalBuffer[Count++] = '\t';
  1559.                         break;
  1560.  
  1561.                         /* Send the current user name. */
  1562.  
  1563.                     case 'U':
  1564.  
  1565.                         break;
  1566.  
  1567.                         /* Send a break across the serial line. */
  1568.  
  1569.                     case 'X':
  1570.  
  1571.                         break;
  1572.  
  1573.                         /* Feed the contents of the
  1574.                          * clipboard into the input
  1575.                          * stream.
  1576.                          */
  1577.  
  1578.                     case 'I':
  1579.  
  1580.                         if(Count)
  1581.                             ConProcess(LocalBuffer,Count);
  1582.  
  1583.                         Count = LoadClip(LocalBuffer,256);
  1584.  
  1585.                         break;
  1586.  
  1587.                         /* Send a string to the clipboard. */
  1588.  
  1589.                     case 'G':
  1590.  
  1591.                         if(String[i + 1])
  1592.                             SaveClip(&String[i + 1],strlen(&String[i + 1]));
  1593.  
  1594.                         return;
  1595.  
  1596.                         /* Produce the escape character. */
  1597.  
  1598.                     case 'E':
  1599.  
  1600.                         LocalBuffer[Count++] = ESC;
  1601.                         break;
  1602.  
  1603.                         /* Call a menu item. */
  1604.  
  1605.                     case 'C':
  1606.  
  1607.                         break;
  1608.  
  1609.                         /* Stuff the character into the buffer. */
  1610.  
  1611.                     default:
  1612.  
  1613.                         LocalBuffer[Count++] = String[i];
  1614.                         break;
  1615.                 }
  1616.  
  1617.                 GotControl = FALSE;
  1618.             }
  1619.         }
  1620.  
  1621.             /* If the buffer is full, release it. */
  1622.  
  1623.         if(Count == 256)
  1624.         {
  1625.             ConProcess(LocalBuffer,Count);
  1626.  
  1627.             Count = 0;
  1628.         }
  1629.     }
  1630.  
  1631.     if(Count)
  1632.         ConProcess(LocalBuffer,Count);
  1633. }
  1634.  
  1635.     /* ConBypass(STRPTR String,LONG Size):
  1636.      *
  1637.      *    Bypass the `normal' ConOutput() data processing.
  1638.      */
  1639.  
  1640. VOID
  1641. ConBypass(STRPTR String,LONG Size)
  1642. {
  1643.     if(Size < 0)
  1644.         Size = strlen(String);
  1645.  
  1646.     if(Size > 0)
  1647.     {
  1648.         VOID (* ProcessData)(STRPTR,LONG);
  1649.  
  1650.         if(Config -> SerialConfig -> StripBit8)
  1651.             ProcessData = ConProcessData7;
  1652.         else
  1653.             ProcessData = ConProcessData8;
  1654.  
  1655.         ObtainSemaphore(&TerminalSemaphore);
  1656.  
  1657.         if(Marking)
  1658.             DropMarker();
  1659.  
  1660.         ClearCursor();
  1661.  
  1662.         (*ProcessData)(String,Size);
  1663.  
  1664.         DrawCursor();
  1665.  
  1666.         ReleaseSemaphore(&TerminalSemaphore);
  1667.     }
  1668. }
  1669.  
  1670.     /* ConProcess(STRPTR String,LONG Size):
  1671.      *
  1672.      *    Process the contents of a string to be sent to the
  1673.      *    console window.
  1674.      */
  1675.  
  1676. VOID
  1677. ConProcess(register STRPTR String,register LONG Size)
  1678. {
  1679.     if(Size > 0)
  1680.     {
  1681.             /* Feed the flow filter. */
  1682.  
  1683.         if(UseFlow)
  1684.         {
  1685.             if(Config -> SerialConfig -> StripBit8)
  1686.                 FlowFilter(String,Size,0x7F);
  1687.             else
  1688.                 FlowFilter(String,Size,0xFF);
  1689.         }
  1690.  
  1691.             /* In quiet mode no characters are echoed to the
  1692.              * console window, they are just passed through
  1693.              * the data flow filter. Usually, this mode is
  1694.              * enabled by the dial panel.
  1695.              */
  1696.  
  1697.         if(!Quiet)
  1698.         {
  1699.                 /* Capture the data. */
  1700.  
  1701.             if(CaptureData)
  1702.             {
  1703.                 if(Config -> CaptureConfig -> ConvertChars && Config -> TerminalConfig -> FontMode != FONT_STANDARD)
  1704.                 {
  1705.                     UBYTE     LocalBuffer[BUFFER_LINE_MAX];
  1706.  
  1707.                     UBYTE    *Src = String,
  1708.                         *Dst,
  1709.                          c;
  1710.  
  1711.                     ULONG     Count,Len = Size;
  1712.  
  1713.                     while(Len > 0)
  1714.                     {
  1715.                         Count = MIN(BUFFER_LINE_MAX,Len);
  1716.  
  1717.                         Len -= Count;
  1718.  
  1719.                         Dst = LocalBuffer;
  1720.  
  1721.                         do
  1722.                         {
  1723.                             if(c = ISOConversion[*Src++])
  1724.                                 *Dst++ = c;
  1725.                             else
  1726.                                 *Dst++ = (UBYTE)'·';
  1727.                         }
  1728.                         while(--Count > 0);
  1729.  
  1730.                         if((Count = (ULONG)Dst - (ULONG)&LocalBuffer[0]) > 0)
  1731.                             (*CaptureData)(LocalBuffer,Count);
  1732.                     }
  1733.                 }
  1734.                 else
  1735.                     (*CaptureData)(String,Size);
  1736.             }
  1737.  
  1738.                 /* Remember the data. */
  1739.  
  1740.             if(RememberOutput)
  1741.                 RememberOutputText(String,Size);
  1742.  
  1743.                 /* Check the traps if necessary. */
  1744.  
  1745.             if(WatchTraps)
  1746.             {
  1747.                 TrapFilter(String,Size);
  1748. /*
  1749. #ifdef FILTER_TRAPS
  1750.                 CaptureParser(TrapStuff,String,Size,TrapFilter);
  1751. #else
  1752.                 TrapFilter(String,Size);
  1753. #endif    // FILTER_TRAPS
  1754. */
  1755.             }
  1756.  
  1757.             if(Marking)
  1758.                 DropMarker();
  1759.  
  1760.             if(TerminalQueue)
  1761.             {
  1762.                 struct DataMsg *Msg;
  1763.  
  1764.                 if(Msg = (struct DataMsg *)CreateMsgItem(sizeof(struct DataMsg) + Size))
  1765.                 {
  1766.                     Msg -> Data = (APTR)(Msg + 1);
  1767.                     Msg -> Size = Size;
  1768.  
  1769.                     CopyMem(String,Msg -> Data,Msg -> Size);
  1770.  
  1771.                     PutMsgItem(TerminalQueue,Msg);
  1772.  
  1773.                     return;
  1774.                 }
  1775.             }
  1776.  
  1777.             ClearCursor();
  1778.  
  1779.             (*ConProcessData)(String,Size);
  1780.  
  1781.             DrawCursor();
  1782.         }
  1783.     }
  1784. }
  1785.  
  1786.     /* ConWrites(STRPTR String,...):
  1787.      *
  1788.      *    Output a string to the console.
  1789.      */
  1790.  
  1791. VOID __stdargs
  1792. ConWrites(STRPTR String,...)
  1793. {
  1794.     va_list    VarArgs;
  1795.  
  1796.     if(Marking)
  1797.         DropMarker();
  1798.  
  1799.     va_start(VarArgs,String);
  1800.     VSPrintf(SharedBuffer,String,VarArgs);
  1801.     va_end(VarArgs);
  1802.  
  1803.     ConProcess(SharedBuffer,strlen(SharedBuffer));
  1804. }
  1805.  
  1806.     /* FlowInit():
  1807.      *
  1808.      *    Set up the data flow parser. The parser scans the serial
  1809.      *    output data for more or less interesting modem output
  1810.      *    (carrier lost, connect, etc.).
  1811.      */
  1812.  
  1813. VOID
  1814. FlowInit(BOOL FullReset)
  1815. {
  1816.     LONG i;
  1817.  
  1818.     for(i = 0 ; i < SCAN_COUNT ; i++)
  1819.         AttentionBuffers[i][0] = 0;
  1820.  
  1821.         /* Set up `NO CARRIER' message. */
  1822.  
  1823.     if(Config -> ModemConfig -> NoCarrier[0])
  1824.         SPrintf(AttentionBuffers[SCAN_NOCARRIER],"%s\r",Config -> ModemConfig -> NoCarrier);
  1825.  
  1826.         /* Set up `CONNECT' message. */
  1827.  
  1828.     strcpy(AttentionBuffers[SCAN_CONNECT],Config -> ModemConfig -> Connect);
  1829.  
  1830.         /* Set up `VOICE' message. */
  1831.  
  1832.     if(Config -> ModemConfig -> Voice[0])
  1833.         SPrintf(AttentionBuffers[SCAN_VOICE],"%s\r",Config -> ModemConfig -> Voice);
  1834.  
  1835.         /* Set up `RING' message. */
  1836.  
  1837.     if(Config -> ModemConfig -> Ring[0])
  1838.         SPrintf(AttentionBuffers[SCAN_RING],"%s\r",Config -> ModemConfig -> Ring);
  1839.  
  1840.         /* Set up `BUSY' message. */
  1841.  
  1842.     if(Config -> ModemConfig -> Busy[0])
  1843.         SPrintf(AttentionBuffers[SCAN_BUSY],"%s\r",Config -> ModemConfig -> Busy);
  1844.  
  1845.         /* Set up `NO DIALTONE' message. */
  1846.  
  1847.     if(Config -> ModemConfig -> NoDialTone[0])
  1848.         SPrintf(AttentionBuffers[SCAN_NODIALTONE],"%s\r",Config -> ModemConfig -> NoDialTone);
  1849.  
  1850.         /* Set up `OK' message. */
  1851.  
  1852.     if(Config -> ModemConfig -> Ok[0])
  1853.         SPrintf(AttentionBuffers[SCAN_OK],"%s\r",Config -> ModemConfig -> Ok);
  1854.  
  1855.         /* Set up `ERROR' message. */
  1856.  
  1857.     if(Config -> ModemConfig -> Error[0])
  1858.         SPrintf(AttentionBuffers[SCAN_ERROR],"%s\r",Config -> ModemConfig -> Error);
  1859.  
  1860.         /* Reset match counter. */
  1861.  
  1862.     FlowCount = 0;
  1863.  
  1864.         /* Reset indices. */
  1865.  
  1866.     memset(AttentionCount,0,sizeof(AttentionCount));
  1867.  
  1868.         /* Determine lengths. */
  1869.  
  1870.     for(i = 0 ; i < SCAN_COUNT ; i++)
  1871.         AttentionLength[i] = strlen(AttentionBuffers[i]);
  1872.  
  1873.     for(i = SCAN_SIGDEFAULTUPLOAD ; i <= SCAN_SIGBINARYDOWNLOAD ; i++)
  1874.     {
  1875.         if(AttentionLength[i] = Config -> TransferConfig -> Signatures[TRANSFERSIG_DEFAULTUPLOAD + i - SCAN_SIGDEFAULTUPLOAD] . Length)
  1876.             CopyMem(Config -> TransferConfig -> Signatures[TRANSFERSIG_DEFAULTUPLOAD + i - SCAN_SIGDEFAULTUPLOAD] . Signature,AttentionBuffers[i],Config -> TransferConfig -> Signatures[TRANSFERSIG_DEFAULTUPLOAD + i - SCAN_SIGDEFAULTUPLOAD] . Length);
  1877.     }
  1878.  
  1879.     if(Config -> TransferConfig -> ASCIIUploadType != XFER_XPR && Config -> TransferConfig -> ASCIIUploadType != XFER_EXTERNALPROGRAM)
  1880.         AttentionLength[SCAN_SIGASCIIUPLOAD] = 0;
  1881.  
  1882.     if(Config -> TransferConfig -> ASCIIDownloadType != XFER_XPR && Config -> TransferConfig -> ASCIIUploadType != XFER_EXTERNALPROGRAM)
  1883.         AttentionLength[SCAN_SIGASCIIDOWNLOAD] = 0;
  1884.  
  1885.     if(Config -> TransferConfig -> TextUploadType != XFER_XPR && Config -> TransferConfig -> TextUploadType != XFER_EXTERNALPROGRAM)
  1886.         AttentionLength[SCAN_SIGTEXTUPLOAD] = 0;
  1887.  
  1888.     if(Config -> TransferConfig -> TextDownloadType != XFER_XPR && Config -> TransferConfig -> TextUploadType != XFER_EXTERNALPROGRAM)
  1889.         AttentionLength[SCAN_SIGTEXTDOWNLOAD] = 0;
  1890.  
  1891.     if(Config -> TransferConfig -> BinaryUploadType != XFER_XPR && Config -> TransferConfig -> BinaryUploadType != XFER_EXTERNALPROGRAM)
  1892.         AttentionLength[SCAN_SIGBINARYUPLOAD] = 0;
  1893.  
  1894.     if(Config -> TransferConfig -> BinaryDownloadType != XFER_XPR && Config -> TransferConfig -> BinaryUploadType != XFER_EXTERNALPROGRAM)
  1895.         AttentionLength[SCAN_SIGBINARYDOWNLOAD] = 0;
  1896.  
  1897.     if(FullReset)
  1898.     {
  1899.             /* No, we are not yet looking for a baud rate. */
  1900.  
  1901.         BaudPending = FALSE;
  1902.  
  1903.             /* Reset the flags. */
  1904.  
  1905.         memset(&FlowInfo,FALSE,sizeof(struct FlowInfo));
  1906.     }
  1907.  
  1908.         /* Full data check is a lot slower than looking for
  1909.          * just a single sequence (such as the `CONNECT'
  1910.          * below). This mode is reserved for the dial panel.
  1911.          */
  1912.  
  1913.     ScanStart    = 0;
  1914.     ScanEnd        = SCAN_COUNT - 1;
  1915.     UseFlow        = TRUE;
  1916. }
  1917.  
  1918.     /* GfxText(struct RastPort *RPort,STRPTR Buffer,LONG Length):
  1919.      *
  1920.      *    Text output, if necessary switching from gfx font
  1921.      *    to current default font.
  1922.      */
  1923.  
  1924. VOID
  1925. GfxText(struct RastPort *RPort,STRPTR Buffer,LONG Length)
  1926. {
  1927.     LONG TextMode;
  1928.     LONG SameMode;
  1929.  
  1930.         /* Determine current text rendering mode. */
  1931.  
  1932.     if(GfxTable[Buffer[0]] == MODE_GFX)
  1933.         TextMode = MODE_GFX;
  1934.     else
  1935.     {
  1936.         TextMode = MODE_STANDARD;
  1937.  
  1938.         SetFont(RPort,TextFont);
  1939.     }
  1940.  
  1941.         /* Reset number of characters in common mode. */
  1942.  
  1943.     SameMode = 0;
  1944.  
  1945.         /* Scan until all input is processed. */
  1946.  
  1947.     FOREVER
  1948.     {
  1949.             /* Scan for characters in the current mode. */
  1950.  
  1951.         while(GfxTable[Buffer[SameMode]] == TextMode && SameMode < Length)
  1952.             SameMode++;
  1953.  
  1954.             /* Output the text found. */
  1955.  
  1956.         Text(RPort,Buffer,SameMode);
  1957.  
  1958.             /* Decrement number of remaining bytes. */
  1959.  
  1960.         Length -= SameMode;
  1961.  
  1962.             /* Anything left? */
  1963.  
  1964.         if(Length)
  1965.         {
  1966.                 /* Skip to next character. */
  1967.  
  1968.             Buffer        += SameMode;
  1969.             SameMode     = 0;
  1970.  
  1971.                 /* Change text output mode. */
  1972.  
  1973.             if(TextMode == MODE_GFX)
  1974.             {
  1975.                 SetFont(RPort,TextFont);
  1976.  
  1977.                 TextMode = MODE_STANDARD;
  1978.             }
  1979.             else
  1980.             {
  1981.                 SetFont(RPort,GFX);
  1982.  
  1983.                 TextMode = MODE_GFX;
  1984.             }
  1985.         }
  1986.         else
  1987.             break;
  1988.     }
  1989.  
  1990.         /* Reset font type. */
  1991.  
  1992.     if(TextMode == MODE_STANDARD)
  1993.         SetFont(RPort,GFX);
  1994. }
  1995.  
  1996.     /* ConvertKey():
  1997.      *
  1998.      *    The actual key conversion routine.
  1999.      */
  2000.  
  2001. STATIC LONG
  2002. ConvertKey(ULONG Qualifier,UWORD Code,ULONG Prev,STRPTR Buffer,LONG Len)
  2003. {
  2004.     LONG Actual;
  2005.  
  2006.         /* Fill in the defaults. */
  2007.  
  2008.     FakeInputEvent -> ie_Code        = Code;
  2009.     FakeInputEvent -> ie_Qualifier        = Qualifier;
  2010.     FakeInputEvent -> ie_position . ie_addr    = (APTR)Prev;
  2011.  
  2012.         /* Clear the buffer (sortof). */
  2013.  
  2014.     Buffer[0] = 0;
  2015.  
  2016.         /* Convert the codes. */
  2017.  
  2018.     if((Actual = RawKeyConvert(FakeInputEvent,Buffer,Len,KeyMap)) > 0)
  2019.         return(Actual);
  2020.     else
  2021.         return(0);
  2022. }
  2023.  
  2024.     /* ConvertTheKey(STRPTR Buffer,LONG *Len,UWORD Code,UWORD Qualifier,ULONG Prev):
  2025.      *
  2026.      *    Much more simplified raw key conversion routine.
  2027.      */
  2028.  
  2029. LONG
  2030. ConvertTheKey(STRPTR Buffer,LONG *Len,UWORD Code,UWORD Qualifier,ULONG Prev)
  2031. {
  2032.     if(Buffer)
  2033.         Buffer[0] = 0;
  2034.  
  2035.     if(Len)
  2036.         *Len = 0;
  2037.  
  2038.         /* Key was pressed, not released. */
  2039.  
  2040.     if(!(Code & IECODE_UP_PREFIX))
  2041.     {
  2042.             /* These are the sequences mapped to special
  2043.              * control keys (cursor keys, function keys,
  2044.              * the help key).
  2045.              */
  2046.  
  2047.         STATIC struct { STRPTR RawCode; UBYTE Result; } ConversionTable[15] =
  2048.         {
  2049.             (STRPTR)"A",    CUP,
  2050.             (STRPTR)"B",    CDN,
  2051.             (STRPTR)"C",    CFW,
  2052.             (STRPTR)"D",    CBK,
  2053.  
  2054.             (STRPTR)"?~",    HLP,
  2055.  
  2056.             (STRPTR)"0~",    FN1,
  2057.             (STRPTR)"1~",    FN2,
  2058.             (STRPTR)"2~",    FN3,
  2059.             (STRPTR)"3~",    FN4,
  2060.             (STRPTR)"4~",    FN5,
  2061.             (STRPTR)"5~",    FN6,
  2062.             (STRPTR)"6~",    FN7,
  2063.             (STRPTR)"7~",    FN8,
  2064.             (STRPTR)"8~",    FN9,
  2065.             (STRPTR)"9~",    F10
  2066.         };
  2067.  
  2068.         STATIC UBYTE SeqLens[15] = { 1,1,1,1,2,2,2,2,2,2,2,2,2,2,2 };
  2069.  
  2070.         UBYTE    ConvertBuffer[257];
  2071.         LONG    Actual;
  2072.  
  2073.             /* If it's a function or cursor key, clear the qualifier. */
  2074.  
  2075.         if(Code >= CURSOR_UP_CODE && Code <= F10_CODE)
  2076.             Qualifier = NULL;
  2077.         else
  2078.         {
  2079.                 /* Does it have a numeric keypad qualifier set? */
  2080.  
  2081.             if((Qualifier & (IEQUALIFIER_NUMERICPAD | IEQUALIFIER_CONTROL)) == (IEQUALIFIER_NUMERICPAD | IEQUALIFIER_CONTROL))
  2082.             {
  2083.                 STRPTR String = NULL;
  2084.  
  2085.                     /* Look at the vanilla result. */
  2086.  
  2087.                 if(ConvertKey(Qualifier & ~(IEQUALIFIER_CONTROL | IEQUALIFIER_LSHIFT | IEQUALIFIER_RSHIFT | IEQUALIFIER_LALT | IEQUALIFIER_RALT),Code,Prev,ConvertBuffer,1))
  2088.                 {
  2089.                         /* Take a look at the results. */
  2090.  
  2091.                     switch(ConvertBuffer[0])
  2092.                     {
  2093.                         case '(':
  2094.                         case '[':
  2095.                         case '{':
  2096.  
  2097.                             String = "\033OP";
  2098.                             break;
  2099.  
  2100.                         case ')':
  2101.                         case ']':
  2102.                         case '}':
  2103.  
  2104.                             String = "\033OQ";
  2105.                             break;
  2106.  
  2107.                         case '/':
  2108.  
  2109.                             String = "\033OR";
  2110.                             break;
  2111.  
  2112.                         case '*':
  2113.  
  2114.                             String = "\033OS";
  2115.                             break;
  2116.  
  2117.                         default:
  2118.  
  2119.                             String = NULL;
  2120.                             break;
  2121.                     }
  2122.                 }
  2123.  
  2124.                 if(!String)
  2125.                 {
  2126.                     switch(Code)
  2127.                     {
  2128.                         case 0x5A:
  2129.  
  2130.                             String = "\033OP";
  2131.                             break;
  2132.  
  2133.                         case 0x5B:
  2134.  
  2135.                             String = "\033OQ";
  2136.                             break;
  2137.  
  2138.                         case 0x5C:
  2139.  
  2140.                             String = "\033OR";
  2141.                             break;
  2142.  
  2143.                         case 0x5D:
  2144.  
  2145.                             String = "\033OS";
  2146.                             break;
  2147.                     }
  2148.                 }
  2149.  
  2150.                     /* Return the PFx key code. */
  2151.  
  2152.                 if(String)
  2153.                 {
  2154.                     if(Buffer)
  2155.                         CopyMem(String,Buffer,3);
  2156.  
  2157.                     if(Len)
  2158.                         *Len = 3;
  2159.  
  2160.                     return('\033');
  2161.                 }
  2162.             }
  2163.  
  2164.                 /* Does it have a shift qualifier set? */
  2165.  
  2166.             if(Qualifier & (IEQUALIFIER_LSHIFT | IEQUALIFIER_RSHIFT))
  2167.             {
  2168.                     /* Do the conversion... */
  2169.  
  2170.                 if(ConvertKey(Qualifier & ~(IEQUALIFIER_LSHIFT | IEQUALIFIER_RSHIFT),Code,Prev,ConvertBuffer,1))
  2171.                 {
  2172.                         /* Did it produce a tab key? If so, transfer
  2173.                          * Esc tab instead.
  2174.                          */
  2175.  
  2176.                     if(ConvertBuffer[0] == '\t')
  2177.                     {
  2178.                         if(Len)
  2179.                             *Len = 2;
  2180.  
  2181.                         if(Buffer)
  2182.                             CopyMem("\033\t",Buffer,2);
  2183.  
  2184.                         return('\033');
  2185.                     }
  2186.                 }
  2187.             }
  2188.  
  2189.                 /* Does it have the control qualifier set? */
  2190.  
  2191.             if(Qualifier & IEQUALIFIER_CONTROL)
  2192.             {
  2193.                     /* Do the conversion... */
  2194.  
  2195.                 if(ConvertKey(Qualifier & ~IEQUALIFIER_CONTROL,Code,Prev,ConvertBuffer,1))
  2196.                 {
  2197.                         /* Did it produce a space or an `at' sign? */
  2198.  
  2199.                     switch(ConvertBuffer[0])
  2200.                     {
  2201.                             /* NUL */
  2202.  
  2203.                         case ' ':
  2204.                         case '@':
  2205.                         case '2':
  2206.  
  2207.                             if(Len)
  2208.                                 *Len = 1;
  2209.  
  2210.                             if(Buffer)
  2211.                                 Buffer[0] = 0;
  2212.  
  2213.                             return(0);
  2214.  
  2215.                             /* Escape */
  2216.  
  2217.                         case '3':
  2218.                         case '[':
  2219.  
  2220.                             if(Len)
  2221.                                 *Len = 1;
  2222.  
  2223.                             if(Buffer)
  2224.                                 Buffer[0] = 0x1B;
  2225.  
  2226.                             return(0x1B);
  2227.  
  2228.                             /* FS */
  2229.  
  2230.                         case '4':
  2231.                         case '/':
  2232.  
  2233.                             if(Len)
  2234.                                 *Len = 1;
  2235.  
  2236.                             if(Buffer)
  2237.                                 Buffer[0] = 0x1C;
  2238.  
  2239.                             return(0x1C);
  2240.  
  2241.                             /* GS */
  2242.  
  2243.                         case '5':
  2244.                         case ']':
  2245.  
  2246.                             if(Len)
  2247.                                 *Len = 1;
  2248.  
  2249.                             if(Buffer)
  2250.                                 Buffer[0] = 0x1D;
  2251.  
  2252.                             return(0x1D);
  2253.  
  2254.                             /* RS */
  2255.  
  2256.                         case '6':
  2257.                         case '~':
  2258.  
  2259.                             if(Len)
  2260.                                 *Len = 1;
  2261.  
  2262.                             if(Buffer)
  2263.                                 Buffer[0] = 0x1E;
  2264.  
  2265.                             return(0x1E);
  2266.  
  2267.  
  2268.                             /* US */
  2269.  
  2270.                         case '7':
  2271.                         case '?':
  2272.  
  2273.                             if(Len)
  2274.                                 *Len = 1;
  2275.  
  2276.                             if(Buffer)
  2277.                                 Buffer[0] = 0x1F;
  2278.  
  2279.                             return(0x1F);
  2280.                     }
  2281.                 }
  2282.             }
  2283.         }
  2284.  
  2285.             /* Do the final conversion... */
  2286.  
  2287.         if(Actual = ConvertKey(Qualifier,Code,Prev,ConvertBuffer,256))
  2288.         {
  2289.                 /* Are we to swap the backspace and
  2290.                  * delete keys?
  2291.                  */
  2292.  
  2293.             if(Config -> EmulationConfig -> SwapBSDelete)
  2294.             {
  2295.                 register LONG i;
  2296.  
  2297.                 for(i = 0 ; i < Actual ; i++)
  2298.                 {
  2299.                     if(ConvertBuffer[i] == BKS)
  2300.                         ConvertBuffer[i] = DEL;
  2301.                     else
  2302.                     {
  2303.                         if(ConvertBuffer[i] == DEL)
  2304.                             ConvertBuffer[i] = BKS;
  2305.                     }
  2306.                 }
  2307.             }
  2308.  
  2309.                 /* Translated sequence starts
  2310.                  * with a CSI, let's have a look
  2311.                  * at the associated control
  2312.                  * key.
  2313.                  */
  2314.  
  2315.             if(ConvertBuffer[0] == CSI)
  2316.             {
  2317.                 register LONG i;
  2318.  
  2319.                 for(i = 0 ; i < sizeof(SeqLens) ; i++)
  2320.                 {
  2321.                         /* Does it match? */
  2322.  
  2323.                     if(!memcmp(&ConvertBuffer[1],ConversionTable[i] . RawCode,SeqLens[i]))
  2324.                     {
  2325.                             /* Store the length. */
  2326.  
  2327.                         if(Len)
  2328.                             *Len = 1;
  2329.  
  2330.                             /* Store the result. */
  2331.  
  2332.                         if(Buffer)
  2333.                         {
  2334.                             Buffer[0] = ConversionTable[i] . Result;
  2335.                             Buffer[1] = 0;
  2336.                         }
  2337.  
  2338.                         return(ConversionTable[i] . Result);
  2339.                     }
  2340.                 }
  2341.             }
  2342.  
  2343.                 /* Store the number of characters converted. */
  2344.  
  2345.             if(Len)
  2346.                 *Len = Actual;
  2347.  
  2348.                 /* Store the converted characters. */
  2349.  
  2350.             if(Buffer)
  2351.                 CopyMem(ConvertBuffer,Buffer,Actual);
  2352.  
  2353.             return(ConvertBuffer[0]);
  2354.         }
  2355.     }
  2356.  
  2357.     return(0);
  2358. }
  2359.  
  2360.     /* KeyConvert(struct IntuiMessage *Massage,STRPTR Buffer):
  2361.      *
  2362.      *    Convert a raw key information according to the
  2363.      *    current keymap settings.
  2364.      */
  2365.  
  2366. LONG
  2367. KeyConvert(struct IntuiMessage *Massage,STRPTR Buffer,LONG *Len)
  2368. {
  2369.         /* Is this really a keyboard event? */
  2370.  
  2371.     if(Massage -> Class == IDCMP_RAWKEY)
  2372.         return(ConvertTheKey(Buffer,Len,Massage -> Code,Massage -> Qualifier,*(ULONG *)Massage -> IAddress));
  2373.     else
  2374.     {
  2375.         if(Buffer)
  2376.             Buffer[0] = 0;
  2377.  
  2378.         if(Len)
  2379.             *Len = 0;
  2380.  
  2381.         return(0);
  2382.     }
  2383. }
  2384.  
  2385.     /* DoBackspace():
  2386.      *
  2387.      *    Special function: perform backspace.
  2388.      */
  2389.  
  2390. BOOL
  2391. DoBackspace()
  2392. {
  2393.     if(CursorX)
  2394.     {
  2395.         LONG DeltaX,MinX;
  2396.  
  2397.         CursorX--;
  2398.  
  2399.             // What backspace mode are we in?
  2400.  
  2401.         switch(Config -> EmulationConfig -> DestructiveBackspace)
  2402.         {
  2403.                 // Do nothing
  2404.  
  2405.             case 0:
  2406.  
  2407.                 RepositionCursor();
  2408.                 break;
  2409.  
  2410.                 // Shift the line to the left
  2411.  
  2412.             case 2:
  2413.  
  2414.                 BackupRender();
  2415.  
  2416.                 RasterEraseCharacters(1);
  2417.  
  2418.                 if(FontScalingRequired)
  2419.                 {
  2420.                     if(CurrentCharWidth == SCALE_NORMAL)
  2421.                     {
  2422.                         DeltaX    = TextFontWidth * 2;
  2423.                         MinX    = MUL_X(CursorX) * 2;
  2424.                     }
  2425.                     else
  2426.                     {
  2427.                         DeltaX    = TextFontWidth / 2;
  2428.                         MinX    = MUL_X(CursorX) / 2;
  2429.                     }
  2430.                 }
  2431.                 else
  2432.                 {
  2433.                     DeltaX    = TextFontWidth;
  2434.                     MinX    = MUL_X(CursorX);
  2435.                 }
  2436.  
  2437.                 ScrollLineEraseCharacters(1);
  2438.  
  2439.                 ScrollLineRaster(RPort,DeltaX,0,MinX,MUL_Y(CursorY),LastPixel,MUL_Y(CursorY + 1) - 1,FALSE);
  2440.  
  2441.                 BackupRender();
  2442.  
  2443.                 RepositionCursor();
  2444.  
  2445.                 break;
  2446.  
  2447.                 // Clear the character below the cursor
  2448.  
  2449.             default:
  2450.  
  2451.                 RepositionCursor();
  2452.  
  2453.                 ObtainSemaphore(RasterSemaphore);
  2454.  
  2455.                 Raster[CursorY * RasterWidth + CursorX] = ' ';
  2456.  
  2457.                 ReleaseSemaphore(RasterSemaphore);
  2458.  
  2459.                 BackupRender();
  2460.  
  2461.                 if(FontScalingRequired)
  2462.                     PrintScaled(" ",1,CurrentFontScale);
  2463.                 else
  2464.                     Text(RPort," ",1);
  2465.  
  2466.                 BackupRender();
  2467.  
  2468.                 break;
  2469.         }
  2470.     }
  2471.  
  2472.     return(FALSE);
  2473. }
  2474.  
  2475.     /* DoBeep():
  2476.      *
  2477.      *    The real interface to the beep routine.
  2478.      */
  2479.  
  2480. BOOL
  2481. DoBeep()
  2482. {
  2483.     BellSignal();
  2484.  
  2485.     return(FALSE);
  2486. }
  2487.  
  2488.     /* DoxON():
  2489.      *
  2490.      *    Perform XON (stop data flow).
  2491.      */
  2492.  
  2493. BOOL
  2494. DoxON()
  2495. {
  2496.     return(FALSE);
  2497. }
  2498.  
  2499.     /* DoLF():
  2500.      *
  2501.      *    Special function: perform line feed.
  2502.      */
  2503.  
  2504. BOOL
  2505. DoLF()
  2506. {
  2507.         // This takes care of regular jump scrolling
  2508.  
  2509.     if(CursorY == Bottom && Bottom > 0 && Config -> EmulationConfig -> MaxJump > 1)
  2510.     {
  2511.         LONG Scroll,TotalLines,OldBack = BackgroundPen;
  2512.  
  2513.         Scroll = Config -> EmulationConfig -> MaxJump;
  2514.  
  2515.             // How tall is the current scroll region?
  2516.  
  2517.         TotalLines = Bottom - Top + 1;
  2518.  
  2519.             // Don't scroll more than the entire screenful
  2520.  
  2521.         if(Scroll > TotalLines)
  2522.             Scroll = TotalLines;
  2523.  
  2524.         if(OldBack)
  2525.         {
  2526.             BackgroundPen = 0;
  2527.  
  2528.             UpdatePens();
  2529.         }
  2530.  
  2531.             // Scroll the region...
  2532.  
  2533.         ScrollRegion(Scroll);
  2534.  
  2535.             // Reposition the cursor
  2536.  
  2537.         if(CursorY > Scroll)
  2538.             CursorY -= Scroll;
  2539.         else
  2540.             CursorY = 0;
  2541.  
  2542.         if(OldBack)
  2543.         {
  2544.             BackgroundPen = OldBack;
  2545.  
  2546.             UpdatePens();
  2547.         }
  2548.     }
  2549.  
  2550.     DownLine();
  2551.  
  2552.     RepositionCursor();
  2553.  
  2554.     return(FALSE);
  2555. }
  2556.  
  2557.     /* DoShiftIn():
  2558.      *
  2559.      *    Special function: Shift into graphics mode
  2560.      */
  2561.  
  2562. BOOL
  2563. DoShiftIn()
  2564. {
  2565.     if(CharMode[1] == TABLE_GFX && GFX)
  2566.         CurrentFont = GFX;
  2567.  
  2568.     if(CharMode[1] == TABLE_ASCII)
  2569.         CurrentFont = TextFont;
  2570.  
  2571.     SetFont(RPort,CurrentFont);
  2572.  
  2573.     ConOutputUpdate();
  2574.  
  2575.     Charset = 1;
  2576.  
  2577.     return(FALSE);
  2578. }
  2579.  
  2580.     /* DoShiftOut():
  2581.      *
  2582.      *    Special function: Shift out of graphics mode
  2583.      */
  2584.  
  2585. BOOL
  2586. DoShiftOut()
  2587. {
  2588.     if(CharMode[0] == TABLE_GFX && GFX)
  2589.         CurrentFont = GFX;
  2590.  
  2591.     if(CharMode[0] == TABLE_ASCII)
  2592.         CurrentFont = TextFont;
  2593.  
  2594.     SetFont(RPort,CurrentFont);
  2595.  
  2596.     ConOutputUpdate();
  2597.  
  2598.     Charset = 0;
  2599.  
  2600.     return(FALSE);
  2601. }
  2602.  
  2603.     /* DoCR_LF():
  2604.      *
  2605.      *    Special function: perform carriage return and line feed.
  2606.      */
  2607.  
  2608. BOOL
  2609. DoCR_LF()
  2610. {
  2611.     CursorX = 0;
  2612.  
  2613.     DownLine();
  2614.  
  2615.     RepositionCursor();
  2616.  
  2617.     return(FALSE);
  2618. }
  2619.  
  2620.     /* DoFF():
  2621.      *
  2622.      *    Special function: perform form feed.
  2623.      */
  2624.  
  2625. BOOL
  2626. DoFF()
  2627. {
  2628.     if(Config -> EmulationConfig -> NewLineMode)
  2629.     {
  2630.         CursorX = 0;
  2631.  
  2632.         DoCR_LF();
  2633.     }
  2634.     else
  2635.     {
  2636.         EraseScreen("2");
  2637.  
  2638.         CursorX = CursorY = 0;
  2639.  
  2640.         RepositionCursor();
  2641.  
  2642.         ConFontScaleUpdate();
  2643.     }
  2644.  
  2645.     return(FALSE);
  2646. }
  2647.  
  2648.     /* DoLF_FF_VT():
  2649.      *
  2650.      *    Special function: handle line feed, form feed and vertical
  2651.      *    tab.
  2652.      */
  2653.  
  2654. BOOL
  2655. DoLF_FF_VT()
  2656. {
  2657.     if(Config -> EmulationConfig -> NewLineMode)
  2658.         DoCR_LF();
  2659.     else
  2660.         DoLF();
  2661.  
  2662.     return(FALSE);
  2663. }
  2664.  
  2665.     /* DoCR():
  2666.      *
  2667.      *    Special function: handle carriage return.
  2668.      */
  2669.  
  2670. BOOL
  2671. DoCR()
  2672. {
  2673.     if(Config -> EmulationConfig -> NewLineMode)
  2674.         DoCR_LF();
  2675.     else
  2676.     {
  2677.         CursorX = 0;
  2678.  
  2679.         RepositionCursor();
  2680.     }
  2681.  
  2682.     return(FALSE);
  2683. }
  2684.  
  2685.     /* DoTab():
  2686.      *
  2687.      *    Special function: handle tab, move cursor to next
  2688.      *    tab stop.
  2689.      */
  2690.  
  2691. BOOL
  2692. DoTab()
  2693. {
  2694.     LONG Column;
  2695.  
  2696.     if(RasterAttr[CursorY] == SCALE_ATTR_NORMAL)
  2697.         Column = LastColumn;
  2698.     else
  2699.         Column = ((LastColumn + 1) / 2) - 1;
  2700.  
  2701.     if(Config -> EmulationConfig -> LineWrap)
  2702.     {
  2703.         if(CursorX >= LastColumn)
  2704.         {
  2705.             CursorX = 0;
  2706.  
  2707.             DownLine();
  2708.         }
  2709.         else
  2710.         {
  2711.             while(CursorX < Column)
  2712.             {
  2713.                 CursorX++;
  2714.  
  2715.                 if(TabStops[CursorX])
  2716.                     break;
  2717.             }
  2718.         }
  2719.     }
  2720.     else
  2721.     {
  2722.         while(CursorX < Column)
  2723.         {
  2724.             CursorX++;
  2725.  
  2726.             if(TabStops[CursorX])
  2727.                 break;
  2728.         }
  2729.     }
  2730.  
  2731.     RepositionCursor();
  2732.  
  2733.     return(FALSE);
  2734. }
  2735.  
  2736.     /* DoEnq():
  2737.      *
  2738.      *    Special function: send answerback message.
  2739.      */
  2740.  
  2741. BOOL
  2742. DoEnq()
  2743. {
  2744.     if(Config -> EmulationConfig -> AnswerBack[0])
  2745.         SerialCommand(Config -> EmulationConfig -> AnswerBack);
  2746.  
  2747.     return(FALSE);
  2748. }
  2749.  
  2750.     /* DoEsc():
  2751.      *
  2752.      *    Start new control sequence.
  2753.      */
  2754.  
  2755. BOOL
  2756. DoEsc()
  2757. {
  2758.     if(Config -> TerminalConfig -> EmulationMode == EMULATION_TTY)
  2759.         (* ConDump)("^",1);
  2760.  
  2761.     return(TRUE);
  2762. }
  2763.  
  2764.     /* DoCsi():
  2765.      *
  2766.      *    Start new control sequence.
  2767.      */
  2768.  
  2769. BOOL
  2770. DoCsi()
  2771. {
  2772.     if(Config -> TerminalConfig -> EmulationMode == EMULATION_TTY)
  2773.         (* ConDump)("^[",2);
  2774.  
  2775.     ParseCode('[');
  2776.  
  2777.     return(TRUE);
  2778. }
  2779.  
  2780.     /* DoNewEsc(LONG Char):
  2781.      *
  2782.      *    Start new control sequence.
  2783.      */
  2784.  
  2785. BOOL
  2786. DoNewEsc(LONG Char)
  2787. {
  2788.     if(Config -> TerminalConfig -> EmulationMode == EMULATION_TTY)
  2789.         (* ConDump)("^",1);
  2790.  
  2791.     DoCancel();
  2792.  
  2793.     InSequence = TRUE;
  2794.  
  2795.     return(TRUE);
  2796. }
  2797.  
  2798.     /* DoNewCsi(LONG Char):
  2799.      *
  2800.      *    Start new control sequence.
  2801.      */
  2802.  
  2803. BOOL
  2804. DoNewCsi(LONG Char)
  2805. {
  2806.     if(Config -> TerminalConfig -> EmulationMode == EMULATION_TTY)
  2807.         (* ConDump)("^[",2);
  2808.  
  2809.     DoCancel();
  2810.  
  2811.     InSequence = TRUE;
  2812.  
  2813.     return(ParseCode('['));
  2814. }
  2815.  
  2816. STATIC STRPTR    CR_Translation,
  2817.         LF_Translation;
  2818. STATIC WORD    CR_Trans_Len,
  2819.         LF_Trans_Len;
  2820.  
  2821. STATIC LONG
  2822. Translate_CR_LF_1(register STRPTR Data,register LONG Size)
  2823. {
  2824.     register STRPTR    String    = Data;
  2825.     register LONG    Count    = 0;
  2826.     register LONG    c;
  2827.  
  2828.     while(Size--)
  2829.     {
  2830.         switch(c = *Data++)
  2831.         {
  2832.             case '\r':
  2833.  
  2834.                 if(CR_Trans_Len)
  2835.                 {
  2836.                     *String++ = *CR_Translation;
  2837.  
  2838.                     Count++;
  2839.                 }
  2840.  
  2841.                 break;
  2842.  
  2843.             case '\n':
  2844.  
  2845.                 if(LF_Trans_Len)
  2846.                 {
  2847.                     *String++ = *LF_Translation;
  2848.  
  2849.                     Count++;
  2850.                 }
  2851.  
  2852.                 break;
  2853.  
  2854.             default:
  2855.  
  2856.                 *String++ = c;
  2857.  
  2858.                 Count++;
  2859.  
  2860.                 break;
  2861.         }
  2862.     }
  2863.  
  2864.     return(Count);
  2865. }
  2866.  
  2867. STATIC LONG
  2868. Translate_CR_LF_2x2(register STRPTR Data,register LONG Size)
  2869. {
  2870.     register STRPTR    String    = Data;
  2871.     register LONG    Count    = 0;
  2872.     register LONG    c;
  2873.  
  2874.     /* ALWAYS */
  2875.     {
  2876.         register BOOL GotIt = FALSE;
  2877.         register LONG i;
  2878.  
  2879.         for(i = 0 ; i < Size ; i++)
  2880.         {
  2881.             if(String[i] == '\r' || String[i] == '\n')
  2882.             {
  2883.                 GotIt = TRUE;
  2884.  
  2885.                 break;
  2886.             }
  2887.         }
  2888.  
  2889.         if(GotIt)
  2890.         {
  2891.             CopyMem(Data,StripBuffer,Size);
  2892.  
  2893.             String    = Data;
  2894.             Data    = StripBuffer;
  2895.         }
  2896.         else
  2897.             return(Size);
  2898.     }
  2899.  
  2900.     while(Size--)
  2901.     {
  2902.         switch(c = *Data++)
  2903.         {
  2904.             case '\r':
  2905.  
  2906.                 if(CR_Trans_Len)
  2907.                 {
  2908.                     register LONG i;
  2909.  
  2910.                     for(i = 0 ; i < CR_Trans_Len ; i++)
  2911.                     {
  2912.                         *String++ = CR_Translation[i];
  2913.  
  2914.                         Count++;
  2915.                     }
  2916.                 }
  2917.  
  2918.                 break;
  2919.  
  2920.             case '\n':
  2921.  
  2922.                 if(LF_Trans_Len)
  2923.                 {
  2924.                     register LONG i;
  2925.  
  2926.                     for(i = 0 ; i < LF_Trans_Len ; i++)
  2927.                     {
  2928.                         *String++ = LF_Translation[i];
  2929.  
  2930.                         Count++;
  2931.                     }
  2932.                 }
  2933.  
  2934.                 break;
  2935.  
  2936.             default:
  2937.  
  2938.                 *String++ = c;
  2939.  
  2940.                 Count++;
  2941.  
  2942.                 break;
  2943.         }
  2944.     }
  2945.  
  2946.     return(Count);
  2947. }
  2948.  
  2949. STATIC LONG
  2950. Translate_CR_LF_2LF(register STRPTR Data,register LONG Size)
  2951. {
  2952.     register STRPTR    String    = Data;
  2953.     register LONG    Count    = 0;
  2954.     register LONG    c;
  2955.  
  2956.     /* ALWAYS */
  2957.     {
  2958.         register BOOL GotIt = FALSE;
  2959.         register LONG i;
  2960.  
  2961.         for(i = 0 ; i < Size ; i++)
  2962.         {
  2963.             if(String[i] == '\n')
  2964.             {
  2965.                 GotIt = TRUE;
  2966.  
  2967.                 break;
  2968.             }
  2969.         }
  2970.  
  2971.         if(GotIt)
  2972.         {
  2973.             CopyMem(Data,StripBuffer,Size);
  2974.  
  2975.             String    = Data;
  2976.             Data    = StripBuffer;
  2977.         }
  2978.         else
  2979.             return(Size);
  2980.     }
  2981.  
  2982.     while(Size--)
  2983.     {
  2984.         switch(c = *Data++)
  2985.         {
  2986.             case '\r':
  2987.  
  2988.                 if(CR_Trans_Len)
  2989.                 {
  2990.                     register LONG i;
  2991.  
  2992.                     for(i = 0 ; i < CR_Trans_Len ; i++)
  2993.                     {
  2994.                         *String++ = CR_Translation[i];
  2995.  
  2996.                         Count++;
  2997.                     }
  2998.                 }
  2999.  
  3000.                 break;
  3001.  
  3002.             case '\n':
  3003.  
  3004.                 if(LF_Trans_Len)
  3005.                 {
  3006.                     register LONG i;
  3007.  
  3008.                     for(i = 0 ; i < LF_Trans_Len ; i++)
  3009.                     {
  3010.                         *String++ = LF_Translation[i];
  3011.  
  3012.                         Count++;
  3013.                     }
  3014.                 }
  3015.  
  3016.                 break;
  3017.  
  3018.             default:
  3019.  
  3020.                 *String++ = c;
  3021.  
  3022.                 Count++;
  3023.  
  3024.                 break;
  3025.         }
  3026.     }
  3027.  
  3028.     return(Count);
  3029. }
  3030.  
  3031. STATIC LONG
  3032. Translate_CR_LF_2CR(register STRPTR Data,register LONG Size)
  3033. {
  3034.     register STRPTR    String    = Data;
  3035.     register LONG    Count    = 0;
  3036.     register LONG    c;
  3037.  
  3038.     /* ALWAYS */
  3039.     {
  3040.         register BOOL GotIt = FALSE;
  3041.         register LONG i;
  3042.  
  3043.         for(i = 0 ; i < Size ; i++)
  3044.         {
  3045.             if(String[i] == '\r')
  3046.             {
  3047.                 GotIt = TRUE;
  3048.  
  3049.                 break;
  3050.             }
  3051.         }
  3052.  
  3053.         if(GotIt)
  3054.         {
  3055.             CopyMem(Data,StripBuffer,Size);
  3056.  
  3057.             String    = Data;
  3058.             Data    = StripBuffer;
  3059.         }
  3060.         else
  3061.             return(Size);
  3062.     }
  3063.  
  3064.     while(Size--)
  3065.     {
  3066.         switch(c = *Data++)
  3067.         {
  3068.             case '\r':
  3069.  
  3070.                 if(CR_Trans_Len)
  3071.                 {
  3072.                     register LONG i;
  3073.  
  3074.                     for(i = 0 ; i < CR_Trans_Len ; i++)
  3075.                     {
  3076.                         *String++ = CR_Translation[i];
  3077.  
  3078.                         Count++;
  3079.                     }
  3080.                 }
  3081.  
  3082.                 break;
  3083.  
  3084.             case '\n':
  3085.  
  3086.                 if(LF_Trans_Len)
  3087.                 {
  3088.                     register LONG i;
  3089.  
  3090.                     for(i = 0 ; i < LF_Trans_Len ; i++)
  3091.                     {
  3092.                         *String++ = LF_Translation[i];
  3093.  
  3094.                         Count++;
  3095.                     }
  3096.                 }
  3097.  
  3098.                 break;
  3099.  
  3100.             default:
  3101.  
  3102.                 *String++ = c;
  3103.  
  3104.                 Count++;
  3105.  
  3106.                 break;
  3107.         }
  3108.     }
  3109.  
  3110.     return(Count);
  3111. }
  3112.  
  3113. VOID
  3114. Update_CR_LF_Translation()
  3115. {
  3116.     Forbid();
  3117.  
  3118.     if(Config -> TerminalConfig -> ReceiveCR == EOL_CRLF || Config -> TerminalConfig -> ReceiveCR == EOL_LFCR || Config -> TerminalConfig -> ReceiveLF == EOL_LFCR || Config -> TerminalConfig -> ReceiveLF == EOL_CRLF)
  3119.         SerialBufferSize = Config -> SerialConfig -> SerialBufferSize / 2;
  3120.     else
  3121.         SerialBufferSize = Config -> SerialConfig -> SerialBufferSize;
  3122.  
  3123.     switch(Config -> TerminalConfig -> ReceiveCR)
  3124.     {
  3125.         case EOL_IGNORE:
  3126.  
  3127.             CR_Trans_Len = 0;
  3128.             break;
  3129.  
  3130.         case EOL_CR:
  3131.  
  3132.             CR_Trans_Len    = 1;
  3133.             CR_Translation    = "\r";
  3134.             break;
  3135.  
  3136.         case EOL_LF:
  3137.  
  3138.             CR_Trans_Len    = 1;
  3139.             CR_Translation    = "\n";
  3140.             break;
  3141.  
  3142.         case EOL_CRLF:
  3143.  
  3144.             CR_Trans_Len    = 2;
  3145.             CR_Translation    = "\r\n";
  3146.             break;
  3147.  
  3148.         case EOL_LFCR:
  3149.  
  3150.             CR_Trans_Len    = 2;
  3151.             CR_Translation    = "\n\r";
  3152.             break;
  3153.     }
  3154.  
  3155.     switch(Config -> TerminalConfig -> ReceiveLF)
  3156.     {
  3157.         case EOL_IGNORE:
  3158.  
  3159.             LF_Trans_Len = 0;
  3160.             break;
  3161.  
  3162.         case EOL_LF:
  3163.  
  3164.             LF_Trans_Len    = 1;
  3165.             LF_Translation    = "\n";
  3166.             break;
  3167.  
  3168.         case EOL_CR:
  3169.  
  3170.             LF_Trans_Len    = 1;
  3171.             LF_Translation    = "\r";
  3172.             break;
  3173.  
  3174.         case EOL_LFCR:
  3175.  
  3176.             LF_Trans_Len    = 2;
  3177.             LF_Translation    = "\n\r";
  3178.             break;
  3179.  
  3180.         case EOL_CRLF:
  3181.  
  3182.             LF_Trans_Len    = 2;
  3183.             LF_Translation    = "\r\n";
  3184.             break;
  3185.     }
  3186.  
  3187.     if(Config -> TerminalConfig -> ReceiveCR == EOL_CR && Config -> TerminalConfig -> ReceiveLF == EOL_LF)
  3188.         Translate_CR_LF = NULL;
  3189.     else
  3190.     {
  3191.         if(LF_Trans_Len <= 1 && CR_Trans_Len <= 1)
  3192.             Translate_CR_LF = Translate_CR_LF_1;
  3193.         else
  3194.         {
  3195.             if(LF_Trans_Len == 2 && CR_Trans_Len == 2)
  3196.                 Translate_CR_LF = Translate_CR_LF_2x2;
  3197.             else
  3198.             {
  3199.                 if(LF_Trans_Len == 2)
  3200.                     Translate_CR_LF = Translate_CR_LF_2LF;
  3201.                 else
  3202.                 {
  3203.                     if(CR_Trans_Len == 2)
  3204.                         Translate_CR_LF = Translate_CR_LF_2CR;
  3205.                     else
  3206.                         Translate_CR_LF = Translate_CR_LF_1;
  3207.                 }
  3208.             }
  3209.         }
  3210.     }
  3211.  
  3212.     Permit();
  3213. }
  3214.